// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/

use std::process::{Command, Stdio};
use tauri::command;
use serde::{Serialize, Deserialize};
use log::{debug, error, info, warn};
use simple_logger::SimpleLogger;

fn setup_logger() {
    SimpleLogger::new()
        .with_level(log::LevelFilter::Debug)
        .init()
        .expect("Failed to initialize logger");
}

#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {}! You've been greeted from Rust!", name)
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    setup_logger();
    info!("Starting Tauri application...");
    
    tauri::Builder::default()
        .plugin(tauri_plugin_opener::init())
        .invoke_handler(tauri::generate_handler![
            greet,
            list_containers,
            create_container,
            remove_container,
            start_container,
            stop_container,
            enter_container
        ])
        .setup(|app| {
            info!("Tauri application setup complete");
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

// 定义与前端一致的容器结构
#[derive(Debug, Serialize, Deserialize)]
struct Container {
    id: String,
    name: String,
    status: ContainerStatus,
    image: String,
    statusText: String,
}

// 容器状态枚举
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
enum ContainerStatus {
    Running,
    Stopped,
    Paused,
    Creating,
}

// 解析 distrobox ls 输出
fn parse_distrobox_output(output: &str) -> Vec<Container> {
    debug!("Parsing distrobox output: {}", output);
    let mut containers = Vec::new();
    let lines: Vec<&str> = output.trim().split('\n').collect();
    
    // 跳过标题行
    for (line_num, line) in lines.iter().skip(1).enumerate() {
        debug!("Processing line {}: {}", line_num, line);
        let parts: Vec<&str> = line
            .split('|')
            .map(|s| s.trim())
            .filter(|s| !s.is_empty())
            .collect();
            
        debug!("Line parts: {:?}", parts);    
        if parts.len() >= 4 {
            let id = parts[0].to_string();
            let name = parts[1].to_string();
            let status_text = parts[2].to_string();
            let image = parts[3].to_string();
            
            // 根据状态文本判断状态
            let status = if status_text.contains("Up") {
                ContainerStatus::Running
            } else if status_text.contains("Exited") {
                ContainerStatus::Stopped
            } else if status_text.contains("Paused") {
                ContainerStatus::Paused
            } else {
                ContainerStatus::Creating
            };
            
            let container = Container {
                id,
                name,
                status,
                image,
                statusText: status_text,
            };
            
            debug!("Parsed container: {:?}", container);
            containers.push(container);
        } else {
            warn!("Line {} does not contain enough parts: {:?}", line_num, parts);
        }
    }
    
    info!("Parsed {} containers from distrobox output", containers.len());
    containers
}

// 定义 Tauri 命令
#[command]
fn list_containers() -> Result<Vec<Container>, String> {
    info!("查询已安装的容器列表...");
    
    // 执行 distrobox ls 命令
    debug!("执行 distrobox ls 命令");
    let output = Command::new("/usr/bin/distrobox")
        .arg("ls")
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .output();
    
    match output {
        Ok(output) => {
            debug!("命令执行成功，解析输出...");
            
            if !output.status.success() {
                let stderr = String::from_utf8_lossy(&output.stderr);
                error!("Command failed with status: {:?}, stderr: {}", output.status, stderr);
                return Err(format!("Command failed: {}", stderr));
            }
            
            let stdout = String::from_utf8_lossy(&output.stdout);
            debug!("Command stdout: {}", stdout);
            
            let containers = parse_distrobox_output(&stdout);
            info!("Successfully listed {} containers", containers.len());
            Ok(containers)
        },
        Err(e) => {
            error!("命令执行失败: {}", e);
            Err(format!("Failed to execute command: {}", e))
        }
    }
}

#[command]
fn create_container(image: &str, name: Option<&str>) -> Result<String, String> {
    info!("创建新容器: image={}, name={:?}", image, name);
    
    let mut command = Command::new("/usr/bin/distrobox");
    command.arg("create");
    
    if let Some(n) = name {
        command.arg("--name").arg(n);
    }
    
    command.arg("--image").arg(image);
    
    let output = command
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .output();
    
    match output {
        Ok(output) => {
            if !output.status.success() {
                let stderr = String::from_utf8_lossy(&output.stderr);
                error!("创建容器失败: {}", stderr);
                return Err(format!("创建容器失败: {}", stderr));
            }
            
            let stdout = String::from_utf8_lossy(&output.stdout);
            info!("容器创建成功: {}", stdout);
            Ok(stdout.to_string())
        },
        Err(e) => {
            error!("执行命令失败: {}", e);
            Err(format!("执行命令失败: {}", e))
        }
    }
}

#[command]
fn remove_container(name: &str) -> Result<String, String> {
    info!("删除容器: {}", name);
    
    let output = Command::new("/usr/bin/distrobox")
        .arg("rm")
        .arg("--force")
        .arg(name)
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .output();
    
    match output {
        Ok(output) => {
            if !output.status.success() {
                let stderr = String::from_utf8_lossy(&output.stderr);
                error!("删除容器失败: {}", stderr);
                return Err(format!("删除容器失败: {}", stderr));
            }
            
            let stdout = String::from_utf8_lossy(&output.stdout);
            info!("容器删除成功: {}", stdout);
            Ok(stdout.to_string())
        },
        Err(e) => {
            error!("执行命令失败: {}", e);
            Err(format!("执行命令失败: {}", e))
        }
    }
}

#[command]
fn start_container(name: &str) -> Result<String, String> {
    info!("启动容器: {}", name);
    
    let output = Command::new("/usr/bin/distrobox")
        .arg("start")
        .arg(name)
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .output();
    
    match output {
        Ok(output) => {
            if !output.status.success() {
                let stderr = String::from_utf8_lossy(&output.stderr);
                error!("启动容器失败: {}", stderr);
                return Err(format!("启动容器失败: {}", stderr));
            }
            
            let stdout = String::from_utf8_lossy(&output.stdout);
            info!("容器启动成功: {}", stdout);
            Ok(stdout.to_string())
        },
        Err(e) => {
            error!("执行命令失败: {}", e);
            Err(format!("执行命令失败: {}", e))
        }
    }
}

#[command]
fn stop_container(name: &str) -> Result<String, String> {
    info!("停止容器: {}", name);
    
    let output = Command::new("/usr/bin/distrobox")
        .arg("stop")
        .arg(name)
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .output();
    
    match output {
        Ok(output) => {
            if !output.status.success() {
                let stderr = String::from_utf8_lossy(&output.stderr);
                error!("停止容器失败: {}", stderr);
                return Err(format!("停止容器失败: {}", stderr));
            }
            
            let stdout = String::from_utf8_lossy(&output.stdout);
            info!("容器停止成功: {}", stdout);
            Ok(stdout.to_string())
        },
        Err(e) => {
            error!("执行命令失败: {}", e);
            Err(format!("执行命令失败: {}", e))
        }
    }
}

#[command]
fn enter_container(name: &str) -> Result<String, String> {
    info!("进入容器: {}", name);
    
    // 使用 opener 插件打开终端
    let terminal = match std::env::var("TERMINAL") {
        Ok(term) => term,
        Err(_) => "xterm".to_string(),
    };
    
    let command = format!("distrobox enter {}", name);
    
    let output = Command::new(terminal)
        .arg("-e")
        .arg(command)
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .spawn();
    
    match output {
        Ok(_) => {
            info!("成功启动终端进入容器");
            Ok("成功启动终端".to_string())
        },
        Err(e) => {
            error!("启动终端失败: {}", e);
            Err(format!("启动终端失败: {}", e))
        }
    }
}    